"""
    libs.adrianrememebrsmeapp.forms
    ===============================

    Validation forms for signup , login and change photo/password
"""

import os, re

from django import forms
from django.utils.translation import ugettext as _

from google.appengine.ext import db

# Django 1.2 versus 1.1
try:
    from django.core.validators import email_re
    from django.core.exceptions import ValidationError
except ImportError, e:
    from django.forms.fields import email_re
    from django.forms import ValidationError

import armsettings
from adrianremembersme import AdrianRemembersMe

def username_validator(username):
    """  Check if username is valid and it's unique """
    username_re = re.compile(armsettings.REGEX_USERNAME)
    if not username_re.match(username):
        raise ValidationError(u'Username may only contain alphanumeric characters or ' \
                               'dashes and cannot begin/end with a dash')

    if not AdrianRemembersMe().username_available( username ):
        raise ValidationError(u'Username is already taken!')


def email_validator(email):
    """  Check if email is valid and it's unique """
    if not email_re.match(email):
        raise ValidationError( _("Please enter a valid e-mail address.") )

    if not AdrianRemembersMe().email_available(email):
        raise ValidationError(u'Email is already taken!')

def password_validator(passwd):
    """ Check password strength """
    if not len(passwd) >= armsettings.PASSWORD_MIN_LEN:
        raise ValidationError(u'Password is not strong enough')






class SignupForm(forms.Form):
    """
    Basic Signup Form with username and email uniqueness.
    """
    username  = forms.CharField( min_length = 3 , max_length = 30 , label=_("Username"), )
    email     = forms.CharField( label=_("E-mail"), )
    name      = forms.CharField( label=_("Name") )
    password  = forms.CharField(  label=_("Password"), min_length=8 , widget=forms.PasswordInput)

    picture = forms.FileField(required=False, label=_("Picture"))

    def clean_username(self):
        username = self.cleaned_data.get('username')
        username_validator(username)
        return username

    def clean_email(self):
        email = self.cleaned_data.get('email')
        email_validator(email)
        return email

    def clean_password(self):
        password = self.cleaned_data.get('password')
        password_validator(password)
        return password
        

class LoginForm(forms.Form):
    """
    Automatically performs login authentication. If is_valid() returns true,
    a Model instance of the valid user is available in cleaned_data['member'].
    """
    username   = forms.CharField( label=_("Username"), min_length = 3 )
    password   = forms.CharField( label=_("Password"), widget=forms.PasswordInput)
    rememberme = forms.BooleanField( label=_("Remember me"), required=False)

    def __init__(self, *args, **kwargs):
        self.request = kwargs.pop('request',None)
        super(LoginForm,self).__init__(*args,**kwargs)

    def clean(self):
        username = self.cleaned_data.get('username')
        password = self.cleaned_data.get('password')
        ip       = self.request.META['REMOTE_ADDR']

        arm    = AdrianRemembersMe()
        member = arm.authenticate( username, password, ip)
        if not member:
            raise ValidationError( _("Please enter a correct username and password.") )

        # Append member to cleaned_data
        self.cleaned_data['member'] = member
        return self.cleaned_data


class ForgotPasswordForm(forms.Form):
    email = forms.EmailField( label=_("E-mail") )

    def clean(self):
        if AdrianRemembersMe().email_available(self.cleaned_data.get('email')):
            raise ValidationError( _("Please provide an registered e-mail address."))

        return self.cleaned_data


class ChangePasswordForm(forms.Form):
    """
    Change user password if it's currently logged in.
    """
    original_password = forms.CharField( label=_("Current password"), widget=forms.PasswordInput)
    new_password      = forms.CharField( label=_("New password"), min_length=6 , widget=forms.PasswordInput)
    new_password_conf = forms.CharField( label=_("New password (Again)"), min_length=6 , widget=forms.PasswordInput)

    def __init__(self, *args, **kwargs):
        self.request = kwargs.pop('request',None)
        super(ChangePasswordForm,self).__init__(*args,**kwargs)

    def clean_new_password(self):
        new_password = self.cleaned_data.get('new_password')
        password_validator(new_password)
        return new_password

    def clean(self):
        original_password = self.cleaned_data.get('original_password')
        new_password      = self.cleaned_data.get('new_password')
        new_password_conf = self.cleaned_data.get('new_password_conf')

        if new_password != new_password_conf:
            raise ValidationError( _("Password confirmation doesn't match!"))

        current_member = self.request.member
        ip             = self.request.META['REMOTE_ADDR']

        arm = AdrianRemembersMe()
        if not arm.authenticate( current_member.name , original_password , ip ):
            raise ValidationError(_("Please enter your current password."))

        return self.cleaned_data


class ResetPasswordForm(forms.Form):
    new_password        = forms.CharField(  label=_("New password"), min_length=6 , widget=forms.PasswordInput)
    new_password_conf   = forms.CharField(  label=_("New password (Again)") , widget=forms.PasswordInput)

    def clean_new_password(self):
        new_password = self.cleaned_data.get('new_password')
        password_validator(new_password)
        return new_password

    def clean(self):
        new_password      = self.cleaned_data.get('new_password')
        new_password_conf = self.cleaned_data.get('new_password_conf')
        if new_password != new_password_conf:
            raise ValidationError( _("Password confirmation doesn't match!"))

        return self.cleaned_data


class ChangeImageForm(forms.Form):
    photo = forms.FileField( label=_("Photo") )
